package com.zsummer.zero.design.create.singleton;

import java.util.concurrent.TimeUnit;

public class Teacher {
	
//	private static Teacher instance;
	// volatile阻止的不singleton = new Singleton()这句话内部[1-2-3]的指令重排，而是保证了在一个写操作（[1-2-3]）完成之前，不会调用读操作（if (instance == null)）
	private static volatile Teacher instance;
	
	private Teacher() {}
	
	// 线程不安全的  耗时22ms
	public static Teacher getInstance() throws InterruptedException {
	if (instance == null) {
		//Thread.sleep(10000);
		TimeUnit.MILLISECONDS.sleep(10);// 和上边的语句等效
		instance = new Teacher();
	}
	return instance;
}
	
	// 添加synchronized同步锁保证只有一个线程进入到这个方法 线程安全 耗时 26ms
//	public static synchronized Teacher getInstance() throws InterruptedException {
//		if (instance == null) {
//			//Thread.sleep(10000);
//			TimeUnit.MILLISECONDS.sleep(10);// 和上边的语句等效
//			instance = new Teacher();
//		}
//		return instance;
//	}
	
	// 双重检查 耗时18ms
//	public static synchronized Teacher getInstance() throws InterruptedException {
//		if (instance == null) {
//			synchronized (Teacher.class) {
//				if (instance == null) {
//					TimeUnit.MILLISECONDS.sleep(3);// 和上边的语句等效
//					instance = new Teacher();
//				}
//			}
//		}
//		return instance;
//	}
	
	// 上边的单利模式还是用可能因为 new Teacher()这个方法不是原子操作，并且由于jvm可能发生的指令重排，造成将中间状态的Teacher对象返回给其他线程
	// 使用volatile关键字 加再instance的声明上，则再new Teacher()方法写入内存的时候，不会去执行instance的读方法。
	
	// 饿汉单利模式
	/*
	public class SingleB {

	    private static final SingleB INSTANCE = new SingleB();

	    private SingleB() {}

	    public static SingleB getInstance() {

	        return INSTANCE;

	    }

	}
	*/
	
	// Effective Java 第一版推荐写法
	/*对于内部类SingletonHolder，它是一个饿汉式的单例实现，在SingletonHolder初始化的时候会由ClassLoader来保证同步，使INSTANCE是一个真·单例。
	同时，由于SingletonHolder是一个内部类，只在外部类的Singleton的getInstance()中被使用，所以它被加载的时机也就是在getInstance()方法第一次被调用的时候。
	——它利用了ClassLoader来保证了同步，同时又能让开发者控制类加载的时机。从内部看是一个饿汉式的单例，但是从外部看来，又的确是懒汉式的实现。
	简直是神乎其技。*/
	/*
	public class Singleton {

	    private static class SingletonHolder {

	        private static final Singleton INSTANCE = new Singleton();

	    }

	    private Singleton (){}

	    public static final Singleton getInstance() {

	        return SingletonHolder.INSTANCE;

	    }

	}
	*/
	
	/*
	// Effective Java 第二版推荐写法
	/*这种写法在功能上与共有域方法相近，但是它更简洁，无偿地提供了序列化机制，绝对防止对此实例化，即使是在面对复杂的序列化或者反射攻击的时候。虽然这中方法还没有广泛采用，但是单元素的枚举类型已经成为实现Singleton的最佳方法。*/
	/*
	public enum SingleInstance {

	    INSTANCE;

	    public void fun1() { 

	        // do something

	    }

	}
	// 使用

	SingleInstance.INSTANCE.fun1();
	*/

}
